﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;

namespace ImageFan.ImageHandling
{
    [DebuggerDisplay("{_fileNameWithPath}")]
    internal class ImageFile
        : IDisposable
    {
        public ImageFile(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                throw new ArgumentException("File name cannot be empty.", "fileName");

            GetFileNameAndPath(fileName);
        }

        public void ReadImageFromDisc()
        {
            CheckAndThrowIfDisposed();
            
            try
            {
                _imageFromDisc = new Bitmap(_fileNameWithPath);
            }
            catch
            {
                _imageFromDisc = GlobalData.InvalidImage;
            }
        }
        
        public Image ImageFromDisc
        {
            get
            {
                CheckAndThrowIfDisposed();

                if (_imageFromDisc == null)
                    ReadImageFromDisc();

                return _imageFromDisc;
            }
        }

        public Image Thumbnail
        {
            get
            {
                CheckAndThrowIfDisposed();

                if (_thumbnail == null)
                {
                    if (_imageFromDisc == null)
                        ReadImageFromDisc();

                    GenerateThumbnail();
                }

                return _thumbnail;
            }
        }

        public Image FullScreenImage
        {
            get
            {
                CheckAndThrowIfDisposed();

                if (_fullScreenImage == null)
                {
                    if (_imageFromDisc == null)
                        ReadImageFromDisc();

                    GenerateFullScreenImage();
                }

                return _fullScreenImage;
            }
        }

        public string FileName
        {
            get
            {
                CheckAndThrowIfDisposed();
                return _fileName;
            }
        }

        public void DisposeImageFromDisc()
        {
            if (_imageFromDisc != null && _imageFromDisc != GlobalData.InvalidImage)
            {
                _imageFromDisc.Dispose();
                _imageFromDisc = null;
            }
        }

        public void DisposeFullScreenImage()
        {
            if (_fullScreenImage != null && _fullScreenImage != GlobalData.InvalidImage)
            {
                _fullScreenImage.Dispose();
                _fullScreenImage = null;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        #region Protected

        protected void Dispose(bool disposing)
        {
            if (!_disposed)
                if (disposing)
                {
                    if (_imageFromDisc != null && _imageFromDisc != GlobalData.InvalidImage)
                    {
                        _imageFromDisc.Dispose();
                        _imageFromDisc = null;
                    }
                    if (_thumbnail != null && _thumbnail != GlobalData.InvalidImageThumbnail &&
                        _thumbnail != GlobalData.LoadingImageThumbnail)
                    {
                        _thumbnail.Dispose();
                        _thumbnail = null;
                    }
                    if (_fullScreenImage != null && _fullScreenImage != GlobalData.InvalidImage)
                    {
                        _fullScreenImage.Dispose();
                        _fullScreenImage = null;
                    }

                    _disposed = true;
                }
        }

        #endregion


        #region Private

        private string _fileName;
        private string _fileNameWithPath;

        private Image _imageFromDisc;
        private Image _thumbnail;
        private Image _fullScreenImage;

        private bool _disposed;

        private void CheckAndThrowIfDisposed()
        {
            if (_disposed)
                throw new ObjectDisposedException(
                    "_image", string.Format("The image '{0}' has already been disposed.",
                                            _fileNameWithPath));
        }

        private void GetFileNameAndPath(string fileName)
        {
            _fileName = Path.GetFileName(fileName);
            _fileNameWithPath = Path.GetFullPath(fileName);
        }

        private void GenerateThumbnail()
        {
            try
            {
                _thumbnail = ImageResizer.CreateThumbnail(_imageFromDisc, GlobalData.ThumbnailSize);
            }
            catch
            {
                _thumbnail = GlobalData.InvalidImageThumbnail;
            }
        }

        private void GenerateFullScreenImage()
        {
            try
            {
                _fullScreenImage = ImageResizer.CreateResizedFullScreenImage(_imageFromDisc);
            }
            catch
            {
                _fullScreenImage = GlobalData.InvalidImage;
            }
        }

        #endregion
    }
}
